package com.tarena.lbs.marketing.web.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tarena.lbs.base.common.utils.Asserts;
import com.tarena.lbs.base.protocol.exception.BusinessException;
import com.tarena.lbs.base.protocol.pager.PageResult;
import com.tarena.lbs.basic.api.BasicApi;
import com.tarena.lbs.common.passport.principle.UserPrinciple;
import com.tarena.lbs.marketing.web.repository.CouponCodeRepository;
import com.tarena.lbs.marketing.web.repository.CouponRepository;
import com.tarena.lbs.marketing.web.utils.AuthenticationContextUtils;
import com.tarena.lbs.pojo.basic.dto.AdminDTO;
import com.tarena.lbs.pojo.marketing.param.CouponParam;
import com.tarena.lbs.pojo.marketing.po.CouponCodePO;
import com.tarena.lbs.pojo.marketing.po.CouponPO;
import com.tarena.lbs.pojo.marketing.query.CouponQuery;
import com.tarena.lbs.pojo.marketing.vo.CouponVO;
import com.tarena.lbs.pojo.stock.param.CouponStockParam;
import com.tarena.lbs.stock.api.StockApi;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.rpc.RpcException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

@Service
@Slf4j
public class CouponService {
    @Autowired
    private CouponRepository couponRepository;
    @Autowired
    private CouponCodeRepository couponCodeRepository;
    //使用dubbo调用接口
    @DubboReference
    private BasicApi basicApi;
    @DubboReference
    private StockApi stockApi;
    public PageResult<CouponVO> pageList(CouponQuery query) throws BusinessException {
        //1.拿到登录用户的userId
        Integer adminId=getUserId();
        //2.获取登录账号的商家id
        Integer businessId=checkAndGetBusinessId(adminId);
        //3.查询当前商家下的优惠券列表
        List<CouponPO> pos= getCouponsByBusinessId(businessId);
        //4.封装返回值
        return assemblePageResult(query,pos);
    }

    private PageResult<CouponVO> assemblePageResult(CouponQuery query, List<CouponPO> pos) {
        //pageNo pageSize total
        PageResult<CouponVO> voPage=
                new PageResult<>(query.getPageSize(),query.getPageNo());
        voPage.setTotal(100l);
        //单独封装po
        if (pos!=null&& pos.size()>0){
            voPage.setObjects(pos.stream().map(po->{
                CouponVO vo=new CouponVO();
                BeanUtils.copyProperties(po,vo);
                return vo;
            }).collect(Collectors.toList()));
        }
        return voPage;
    }

    private List<CouponPO> getCouponsByBusinessId(Integer businessId) {
        //select * from coupon where business_id=?
        QueryWrapper<CouponPO> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("business_id",businessId);
        return couponRepository.list(queryWrapper);
    }

    private Integer checkAndGetBusinessId(Integer adminId) throws BusinessException {
        //设计dubbo调用接口
        //远程调用 查询adminDto 断言空 返回businessId
        log.info("marketing调用basic,adminId:{}",adminId);
        AdminDTO adminDTO = basicApi.getAdminDetail(adminId);
        Asserts.isTrue(adminDTO==null,new BusinessException("-2","商家信息获取失败"));
        log.info("marketing调用basic,adminId:{},adminDTO:{}",adminId,adminDTO);
        return adminDTO.getBusinessId();
    }

    private Integer getUserId() throws BusinessException {
        UserPrinciple userPrinciple = AuthenticationContextUtils.get();
        Asserts.isTrue(userPrinciple==null,new BusinessException("-2","认证解析失败"));
        return userPrinciple.getId();
    }

    @Transactional(rollbackFor = Exception.class)
    public void save(CouponParam couponParam) throws BusinessException {
        //1.获取登录用户id
        Integer adminId = getUserId();
        //2.获取businessId
        Integer businessId=checkAndGetBusinessId(adminId);
        //3.封装CouponPO 补充一些属性 调用仓储层新增
        CouponPO couponPo=assembleCouponPO(couponParam,businessId);
        couponRepository.save(couponPo);
        //4.使用优惠券生成的数据couponId 绑定发行量个数个code券码 新增券码
        //List<CouponCodePO> codePos=assembleCouponCodes(couponPo);
        //log.info("初始化当前优惠券:{},券码个数:{}",couponPo.getId(),codePos.size());
        //缺少CouponCodeRepository
        //couponCodeRepository.saveBatch(codePos,100);
        //5.初始化库存
        initCouponStock(couponPo);
    }

    private void initCouponStock(CouponPO couponPo) throws BusinessException {
        //调用stockApi初始化库存,封装param
        CouponStockParam param=new CouponStockParam();
        param.setCouponId(couponPo.getId());
        param.setNum(couponPo.getMaxUsageLimit());
        param.setBusinessId(couponPo.getBusinessId());
        try {
            boolean result = stockApi.initCouponStock(param);
            if (!result){
                throw new BusinessException("-2","调用库存初始化失败 请联系库存查看日志");
            }
        }catch (RpcException e){
            //意味着远程通信 连接有问题
            throw new BusinessException("-2","库存连接失败,初始化异常");
        }
    }

    private List<CouponCodePO> assembleCouponCodes(CouponPO couponPo) {
        //根据couponPo里最大发行量数据 生成List<CouponCodePO>
        Integer count = couponPo.getMaxUsageLimit();
        List<CouponCodePO> pos=new ArrayList<>();
        for(int i=0;i<count;i++){
            //创建一个code券码实体
            CouponCodePO po=new CouponCodePO();
            po.setCouponId(couponPo.getId());
            po.setBusinessId(couponPo.getBusinessId());
            po.setStatus(0);//0未使用 1已使用 2已过期
            po.setCouponCode(UUID.randomUUID().toString());
            po.setCreateAt(couponPo.getCreateAt());
            po.setUpdateAt(couponPo.getUpdateAt());
            pos.add(po);
        }
        return pos;
    }

    private CouponPO assembleCouponPO(CouponParam couponParam, Integer businessId) throws BusinessException {
        //1.拷贝表单参数
        CouponPO po=new CouponPO();
        BeanUtils.copyProperties(couponParam,po);
        //2.补充表单没有提交的数据 主要防止数据库报异常 not null
        po.setBusinessId(businessId);
        po.setStatus(1);
        po.setEnableStatus(1);
        po.setCreateAt(new Date());
        po.setUpdateAt(new Date());
        //springmvc 数据封装 默认不能将"2024-12-25 0:0:0"这个字符串转化成date 类型 localdatetime类型
        try {
            po.setStartDate(DateUtils.parseDate(couponParam.getStartDate(), "yyyy-MM-dd HH:mm:ss"));
            po.setEndDate(DateUtils.parseDate(couponParam.getEndDate(), "yyyy-MM-dd HH:mm:ss"));
        }catch (ParseException e){
            log.error("时间字符串转化异常",e);
            throw new BusinessException("-2","出现异常停止新增");
        }
        return po;
    }

    public CouponVO detail(Integer id) {
        CouponPO po = couponRepository.getById(id);
        if (po!=null){
            CouponVO vo=new CouponVO();
            BeanUtils.copyProperties(po,vo);
            return vo;
        }
        return null;
    }
}
